package com.cg.asm.body.service.roles.impl;

import com.cg.asm.body.dao.roles.RoleFunMapper;
import com.cg.asm.body.domain.dto.roles.RoleFunDTO;
import com.cg.asm.body.domain.dto.roles.RoleFunPointsDTO;
import com.cg.asm.body.domain.vo.roles.RoleFunPointsVO;
import com.cg.asm.body.domain.vo.roles.RoleFunTreeVO;
import com.cg.asm.body.domain.vo.roles.RoleFunVO;
import com.cg.asm.body.domain.vo.roles.RolePointsSaveVO;
import com.cg.asm.body.service.roles.IRoleFunService;
import com.cg.asm.body.util.AsmBodyCommonUtil;
import com.cg.asm.client.AsmUUID;
import com.cg.asm.client.domain.user.UserInfo;
import com.cg.asm.client.exception.AsmException;
import com.github.pagehelper.util.StringUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
public class RoleFunService implements IRoleFunService {

    private final RoleFunMapper roleFunMapper;

    public RoleFunService(RoleFunMapper roleFunMapper) {
        this.roleFunMapper = roleFunMapper;
    }

    @Override
    public List<RoleFunTreeVO> getMenuTreeData() {
        UserInfo userLoginVO = AsmBodyCommonUtil.getCurrentUserLoginVO();
        List<RoleFunTreeVO> managerFunList = null;
        if (null != userLoginVO) {
            String userId = userLoginVO.getUserId();
            if ("super".equals(userId)) {
                //super获取所有功能清单信息
                managerFunList = roleFunMapper.getFunListByExecute();
            } else {
                //根据用户名称获取用户所有管理角色的功能清单信息
                managerFunList = roleFunMapper.getUserManagerFunList(userId);
            }
        }
        //获取所有分组类功能清单
        List<RoleFunTreeVO> menuGroups = roleFunMapper.getFunListByGroup();

        //存储用户管理的功能清单:包含功能类、分组类
        Map<String, RoleFunTreeVO> menuByManager = new HashMap<>();

        //根据用户功能清单，查找所有父级功能清单信息
        //并存储到menuByManager数据集中
        for (RoleFunTreeVO managerMenu : managerFunList) {
            if (null != managerMenu) {
                menuByManager.put(managerMenu.getSelfLevelCode(), managerMenu);
                String parentCode = managerMenu.getParentLevelCode();
                if (StringUtil.isNotEmpty(parentCode)) {
                    this.findParentMenu(menuByManager, menuGroups, parentCode);
                }
            }
        }

        //存储功能清单树信息
        List<RoleFunTreeVO> funListTree = new ArrayList<>();

        //根据userMenuByAll数据集构建功能清单树
        //并存储到userMenuTree数据集中
        for (String levelCode : menuByManager.keySet()) {
            RoleFunTreeVO roleFunTreeVO = menuByManager.get(levelCode);
            if (null != roleFunTreeVO) {
                if (StringUtil.isEmpty(roleFunTreeVO.getParentLevelCode())) {
                    this.findChildrenMenu(roleFunTreeVO, menuByManager);
                    funListTree.add(roleFunTreeVO);
                }
            }
        }

        if (funListTree.size() != 0) {
            this.listSort(funListTree);
        }

        return funListTree;
    }

    /**
     * 根据父级层级编码查找所有父级信息
     *
     * @param menuByManager 存储根据父级编码查询出的父级信息
     * @param menuGroups    所有分组功能清单
     * @param parentCode    父级编码
     */
    private void findParentMenu(Map<String, RoleFunTreeVO> menuByManager, List<RoleFunTreeVO> menuGroups, String parentCode) {
        for (RoleFunTreeVO menuGroup : menuGroups) {
            if (null != menuGroup) {
                String selfLevelCode = menuGroup.getSelfLevelCode();
                if (parentCode.equals(selfLevelCode)) {
                    if (!menuByManager.containsKey(selfLevelCode)) {
                        menuByManager.put(selfLevelCode, menuGroup);
                        String parentLevel = menuGroup.getParentLevelCode();
                        if (StringUtil.isNotEmpty(parentLevel)) {
                            this.findParentMenu(menuByManager, menuGroups, parentLevel);
                        }
                    }
                }
            }
        }
    }

    /**
     * 根据顶级菜单构建所有子集
     *
     * @param menu
     * @param menuByManager
     */
    private void findChildrenMenu(RoleFunTreeVO menu, Map<String, RoleFunTreeVO> menuByManager) {
        List<RoleFunTreeVO> menuUserLoginList = new ArrayList<>();
        for (String levelCode : menuByManager.keySet()) {
            RoleFunTreeVO childrenMenu = menuByManager.get(levelCode);
            if (null != childrenMenu) {
                if (menu.getSelfLevelCode().equals(childrenMenu.getParentLevelCode())) {
                    menuUserLoginList.add(childrenMenu);
                    this.findChildrenMenu(childrenMenu, menuByManager);
                }
            }
        }
        if (menuUserLoginList.size() != 0) {
            if (menuUserLoginList.size() != 0) {
                this.listSort(menuUserLoginList);
            }
            menu.setChildren(menuUserLoginList);
        }
    }

    @Override
    public List<RoleFunPointsVO> getMenuPointsData(String funListCode) {
        return roleFunMapper.getMenuPointsData(funListCode);
    }

    @Override
    public List<String> getRoleFunPointsCode(String roleId, String funListCode) {
        List<String> roleFunPoints = roleFunMapper.getRoleFunPointsCode(roleId, funListCode);
        if (null != roleFunPoints && roleFunPoints.size() != 0) {
            //如果当前角色已选择当前功能清单的功能点，则返回选择结果
            return roleFunPoints;
        } else {
            //如果当前角色未选择过当前功能清单的功能点，则返回默认值
            return roleFunMapper.getRoleFunPointsDefault(funListCode);
        }
    }

    @Override
    public List<String> restorePointsDefaults(String funListCode) {
        return roleFunMapper.getRoleFunPointsDefault(funListCode);
    }

    @Override
    public List<String> getRoleFunListCodes(String roleId) {
        return roleFunMapper.getRoleFunListCodes(roleId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveRoleMenu(RoleFunVO roleFunVO) {
        if (null != roleFunVO && StringUtil.isNotEmpty(roleFunVO.getRoleId())) {
            if (null != roleFunVO.getFunListCodes()) {
                //根据角色Id删除所有的功能清单
                roleFunMapper.delRoleFun(roleFunVO.getRoleId());
                for (String funListCode : roleFunVO.getFunListCodes()) {
                    RoleFunDTO roleFunDTO = new RoleFunDTO();
                    roleFunDTO.setRoleFunCode(AsmUUID.generate());
                    roleFunDTO.setRoleId(roleFunVO.getRoleId());
                    roleFunDTO.setFunListCode(funListCode);
                    roleFunMapper.saveRoleFun(roleFunDTO);
                }
                //获取需保存的功能点信息
                Map<String, List<String>> pointsMap = this.cleaningPointsInfo(roleFunVO);
                //根据角色Id删除之前设置的所有功能点
                roleFunMapper.delRoleFunPoints(roleFunVO.getRoleId());
                //为角色选中的功能清单设置功能点
                for (String funListCodeKey : pointsMap.keySet()) {
                    List<String> pointsValue = pointsMap.get(funListCodeKey);
                    if (null != pointsValue && pointsValue.size() != 0) {
                        for (String pointsCode : pointsValue) {
                            RoleFunPointsDTO roleFunPointsDTO = new RoleFunPointsDTO();
                            roleFunPointsDTO.setRoleFunPoints(AsmUUID.generate());
                            roleFunPointsDTO.setFunListCode(funListCodeKey);
                            roleFunPointsDTO.setFunPointsCode(pointsCode);
                            roleFunPointsDTO.setRoleId(roleFunVO.getRoleId());
                            roleFunMapper.saveRoleFunPoints(roleFunPointsDTO);
                        }
                    }
                }
            }
        } else {
            throw new AsmException("分配功能清单失败：缺失角色ID信息");
        }
    }

    /**
     * 功能点数据转换成Map数据集
     *
     * @param rolePoints
     * @return
     */
    private Map<String, List<String>> pointConvertToMap(List<RolePointsSaveVO> rolePoints) {
        Map<String, List<String>> pointConfigMap = new HashMap<>();
        if (null != rolePoints) {
            for (RolePointsSaveVO rolePointsSaveVO : rolePoints) {
                if (null != rolePointsSaveVO && StringUtil.isNotEmpty(rolePointsSaveVO.getFunListCode())) {
                    pointConfigMap.put(rolePointsSaveVO.getFunListCode(), rolePointsSaveVO.getPointCodes());
                }
            }
        }
        return pointConfigMap;
    }

    /**
     * 清洗需保存的功能点信息
     *
     * @return
     */
    private Map<String, List<String>> cleaningPointsInfo(RoleFunVO roleFunVO) {
        String roleId = roleFunVO.getRoleId();
        List<String> funListCodes = roleFunVO.getFunListCodes();
        //本次设置手工配制的所有功能点
        Map<String, List<String>> manualConfigMap = this.pointConvertToMap(roleFunVO.getFunListPoints());
        //角色设置时已经保存过的功能点
        List<RolePointsSaveVO> roleFunPoints = roleFunMapper.getroleFunPoints(roleId, funListCodes);
        setDefaultPoint(manualConfigMap, roleFunPoints);
        //功能清单设置的所有默认选中的功能点
        List<RolePointsSaveVO> defaultPointsByAllArray = roleFunMapper.getDefaultPointsByFunListCodes(funListCodes);
        setDefaultPoint(manualConfigMap, defaultPointsByAllArray);
        return manualConfigMap;
    }

    /**
     * 设置默认选中功能点
     *
     * @param manualConfigMap
     * @param roleFunPoints
     */
    private void setDefaultPoint(Map<String, List<String>> manualConfigMap, List<RolePointsSaveVO> roleFunPoints) {
        for (RolePointsSaveVO savePonits : roleFunPoints) {
            String saveFunListCode = savePonits.getFunListCode();
            if (null != savePonits && StringUtil.isNotEmpty(saveFunListCode)) {
                if ((manualConfigMap.containsKey(saveFunListCode)) == false) {
                    List<String> points = savePonits.getPointCodes();
                    if (null != points && points.size() != 0) {
                        manualConfigMap.put(saveFunListCode, points);
                    }
                }
            }
        }
    }

    /**
     * 集合排序
     *
     * @param sortArray
     */
    private void listSort(List<RoleFunTreeVO> sortArray) {
        Collections.sort(sortArray, Comparator.comparing(RoleFunTreeVO::getFunListOrder));
    }
}
